// OpenCppCoverage is an open source code coverage for C++.
// Copyright (C) 2019 OpenCppCoverage

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include <boost/program_options/variables_map.hpp>
#include "Tools/Tool.hpp"
#include "CppCoverageException.hpp"

namespace CppCoverage
{
	class ProgramOptionsVariablesMap
	{
	  public:
		//---------------------------------------------------------------------
		ProgramOptionsVariablesMap() = default;

		//---------------------------------------------------------------------
		template <typename T>
		const T* GetOptionalValue(const std::string& optionName) const
		{
			auto it = variables_map_.find(optionName);

			if (it == variables_map_.end())
				return nullptr;
			const auto& variable = it->second;

			return &variable.as<T>();
		}

		//---------------------------------------------------------------------
		template <typename T>
		const T& GetValue(const std::string& optionName) const
		{
			auto* optionalValue = GetOptionalValue<T>(optionName);

			if (!optionalValue)
				THROW(L"Cannot find option:" +
				      Tools::LocalToWString(optionName));

			return *optionalValue;
		}

		//---------------------------------------------------------------------
		bool IsOptionSelected(const std::string& optionName) const
		{
			return variables_map_.find(optionName) != variables_map_.end();
		}

		//---------------------------------------------------------------------
		using VariableMap = boost::program_options::variables_map;

		VariableMap& GetVariablesMap()
		{
			return variables_map_;
		}

	  private:
		ProgramOptionsVariablesMap(const ProgramOptionsVariablesMap&) = delete;
		ProgramOptionsVariablesMap&
		operator=(const ProgramOptionsVariablesMap&) = delete;

		VariableMap variables_map_;
	};
}